<template>
  <div class="page_root" :key="queryUpdateFlag" data-page-name="faq问题" data-page-identification="g_fg9mt2lh8c">
    <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
      <!-- begin vid_bdcd4dofka 自定义模板_da85dlu48q -->
      <!--            回答-->
      <a-modal
        :visible="state.answerVisible"
        title="回答"
        centered
        :mask-closable="false"
        @ok="handleConfirmAnswer"
        @cancel="cancelAnswer"
        width="1000px"
        destroy-on-close
        :ok-button-props="{ loading: state.answerLoading }"
      >
        <div class="add-or-edit-faq">
          <a-form :model="state.answerForm" ref="answerRef">
            <a-row>
              <a-col :span="24">
                <a-form-item label="" :rules="[{ required: true, message: '请输入回答', trigger: 'blur' }]" name="answer">
                  <!--                                    <a-textarea-->
                  <!--                                        placeholder="请输入回答"-->
                  <!--                                        show-count-->
                  <!--                                        :rows="2"-->
                  <!--                                        v-model:value="state.answerForm.answer"-->
                  <!--                                    />-->
                  <QuillEditor v-model:content="state.answerForm.answer" ref="quillEditor" :options="editorOption" class="quill-editor" />
                </a-form-item>
              </a-col>
            </a-row>
          </a-form>
        </div>
      </a-modal>
      <!--            回答-->
      <!--            新建/编辑FAQ-->
      <a-modal
        :visible="state.addOrEditFaqVisible"
        :title="state.addOrEditTitle"
        centered
        :mask-closable="false"
        @ok="handleConfirmFaq"
        @cancel="cancelAdd"
        width="1000px"
        destroy-on-close
        :ok-button-props="{ loading: state.addLoading }"
      >
        <div class="add-or-edit-faq">
          <a-form :model="state.modalForm" ref="faqRef">
            <a-row>
              <!--                            <a-col :span="24">-->
              <!--                                <a-form-item-->
              <!--                                    label="情景"-->
              <!--                                    :rules="[{ required: true, message: '请输入情景', trigger: 'blur' }]"-->
              <!--                                    name="scene"-->
              <!--                                >-->
              <!--                                    <a-textarea :rows="2" v-model:value="state.modalForm.scene" />-->
              <!--                                </a-form-item>-->
              <!--                            </a-col>-->
              <a-col :span="24">
                <a-form-item label="问题名称" :rules="[{ required: true, message: '请输入问题名称', trigger: 'blur' }]" name="problemName">
                  <a-textarea show-count :maxlength="100" :rows="2" v-model:value="state.modalForm.problemName" />
                </a-form-item>
              </a-col>
              <a-col :span="24">
                <a-form-item label="项目阶段" :rules="[{ required: true, message: '请输入问题名称', trigger: 'blur' }]" name="stageNames">
                  <a-textarea placeholder="请输入，不同项目阶段根据“;”区分" show-count :rows="2" v-model:value="state.modalForm.stageNames" />
                </a-form-item>
              </a-col>
              <a-col :span="24">
                <a-form-item label="标签" :rules="[{ required: true, message: '请输入标签', trigger: 'blur' }]" name="labels">
                  <a-textarea placeholder="请输入，不同标签根据“;”区分" show-count :rows="2" v-model:value="state.modalForm.labels" />
                </a-form-item>
              </a-col>
            </a-row>
          </a-form>
        </div>
      </a-modal>
      <!--            新建/编辑FAQ-->
      <a-spin :spinning="state.dataloading" tip="加载中">
        <div class="body" :style="getBodyStyle()">
          <a-row :gutter="24">
            <a-col :span="6">
              <a-form-item label="关键字">
                <a-input placeholder="请输入关键字或标签检索" v-model:value="state.keyWords" @input="debouncedGetData" />
              </a-form-item>
            </a-col>
            <a-col :span="2">
              <a-button @click="resetData" type="primary" ghost>重置</a-button>
            </a-col>
            <!-- end vid_hwx83rvzpu 我的 -->
            <!-- begin vid_eaymhbrupq 审批 -->
            <a-col :span="2" offset="14" style="display: flex; justify-content: end">
              <a-button type="primary" @click="handleAddFaq">
                <template #icon><PlusOutlined /></template>
                新建
              </a-button>
            </a-col>
          </a-row>
          <div class="gd-template-scroll">
            <template v-if="state.dataList.length == 0">
              <div class="no-data-img"></div>
              <div class="no-data-msg">暂无数据</div>
            </template>
            <div class="gd-item" v-for="(item, index) in state.dataList" :key="item.id">
              <div class="template-item-title">
                <div class="item-left">
                  <div class="item-top">
                    <div class="top-left-div">
                      <div class="item-name" @click="jumpDetail(item.id)">
                        <div class="count">{{ index + 1 }} <div class="count-under"></div> </div>{{ item.problemName }}</div
                      >
                    </div>
                  </div>
                </div>
                <div class="tem-right">
                  <div class="top-right-div" @click.stop="onClick">
                    <a-space :size="8">
                      <a-button type="primary" ghost size="small" class="btn-item" @click="handleShowAnswer(item)">回答 </a-button>

                      <a-button type="primary" ghost size="small" class="btn-item" @click="handlEditFaq(item)" :disabled="!item.operateFlag">编辑 </a-button>
                      <a-popconfirm title="确认删除吗?" ok-text="确定" cancel-text="取消" :disabled="!item.operateFlag" @confirm="handleConfirmDelete(item.id)" @cancel="cancel">
                        <a-button :disabled="!item.operateFlag" type="primary" ghost size="small">删除</a-button>
                      </a-popconfirm>
                      <a-button type="primary" ghost size="small" @click="jumpDetail(item.id)">详情</a-button>
                    </a-space>
                  </div>
                </div>
              </div>
              <div class="icon-main">
                <div class="item-icon">
                  <a-tag style="color: #52c41a" v-for="(tag, index) in item.labelList" :key="'label-' + index" :color="colorList[0]" :bordered="false">
                    {{ tag }}
                  </a-tag>

                  <!-- stageNameList 标签，使用 colorList[1] -->
                  <a-tag style="color: #fa8c16" v-for="(tag, index) in item.stageNameList" :key="'stage-' + index" :color="colorList[1]" :bordered="false">
                    {{ tag }}
                  </a-tag>
                </div>
                <div class="item-bottom">
                  <div class="bottom-top-item">
                    <span class="bottom-top-title">创建人：</span>
                    <span class="bottom-top-msg">{{ item.createdBy }}</span></div
                  >
                  <div class="bottom-top-item">
                    <span class="bottom-top-title">创建时间：</span>
                    <span class="bottom-top-msg">{{ item.createdTime }}</span></div
                  >
                </div>
              </div>

              <div class="answer-item" v-if="item.answer" :key="index">
                <div class="btn-title">
                  <div class="btn-left">
                    <div class="btn-img"></div>
                    <div class="btn-name">置顶回答</div>
                  </div>
                  <a-space>
                    <a-button
                      style="padding: 0"
                      type="link"
                      size="small"
                      @click="changeStatus(item.answer, index)"
                      :disabled="!item.answer.operateFlag"
                      :loading="item.answer.loading"
                      >{{ item.answer.display ? '取消置顶' : '增加置顶' }}</a-button
                    >
                    <div class="line"></div>
                    <a-button style="padding: 0" type="link" size="small" @click="handleEditAnswer(item.answer, index)" :disabled="!item.answer.operateFlag">编辑</a-button>
                    <div class="line"></div>
                    <a-popconfirm
                      title="确认删除这条回答吗?"
                      ok-text="确定"
                      cancel-text="取消"
                      :disabled="!item.answer.operateFlag"
                      @confirm="handleConfirmDeleteAnswer(item.answer.id)"
                      @cancel="cancel"
                    >
                      <a-button style="padding: 0" type="link" :disabled="!item.answer.operateFlag" size="small">删除</a-button>
                    </a-popconfirm>
                    <a-button style="padding: 0" type="link" size="small" @click="toggleExpand(index)">
                      {{ expandedIndex === index ? '收起' : '阅读全文'

                      }}<UpOutlined v-if="expandedIndex === index" /> <DownOutlined v-else />
                    </a-button>
                  </a-space>
                </div>
                <div class="answer-content">
                  <div class="answer-preview" :class="{ expanded: expandedIndex === index }" v-html="getHtmlContent(item.answer.answer)"></div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </a-spin>
      <!-- end vid_bdcd4dofka 自定义模板_da85dlu48q -->
      <!-- begin vid_wbjfcw4z9r 容器_gb3xm45m4n -->
      <al-box v-if="false" class="vid_wbjfcw4z9r">
        <!-- begin vid_i9qutm9s24 删除 -->
        <a-button v-permission="'3000001016_vid_i9qutm9s24'" class="vid_i9qutm9s24"> 删除 </a-button>
        <!-- end vid_i9qutm9s24 删除 -->
        <!-- begin vid_qpqhaunz1y 编辑 -->
        <a-button v-permission="'3000001016_vid_qpqhaunz1y'" class="vid_qpqhaunz1y"> 编辑 </a-button>
        <!-- end vid_qpqhaunz1y 编辑 -->
        <!-- begin vid_230y7a3epu 置顶 -->
        <a-button v-permission="'3000001016_vid_230y7a3epu'" class="vid_230y7a3epu"> 置顶 </a-button>
        <!-- end vid_230y7a3epu 置顶 -->
        <!-- begin vid_f3635cbyfy 回答 -->
        <a-button v-permission="'3000001016_vid_f3635cbyfy'" class="vid_f3635cbyfy"> 回答 </a-button>
        <!-- end vid_f3635cbyfy 回答 -->
        <!-- begin vid_zvzhxtmham 详情 -->
        <a-button v-permission="'3000001016_vid_zvzhxtmham'" class="vid_zvzhxtmham"> 详情 </a-button>
        <!-- end vid_zvzhxtmham 详情 -->
        <!-- begin vid_0qeikpreii 新建问题 -->
        <a-button v-permission="'3000001016_vid_0qeikpreii'" class="vid_0qeikpreii"> 新建问题 </a-button>
        <!-- end vid_0qeikpreii 新建问题 -->
      </al-box>
      <!-- end vid_wbjfcw4z9r 容器_gb3xm45m4n -->
    </a-spin>
  </div>
</template>
<script setup lang="tsx">
  import {
      h, ref, reactive, toRaw, markRaw, watch, computed,
      onBeforeMount, onMounted, onBeforeUnmount, onUnmounted, onActivated, onDeactivated
    } from "vue";
    import { useRoute, useRouter } from 'vue-router';
    const router = useRouter();
    const route = useRoute();
    import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios';
    import { cloneDeep, localGet, merge, getDifferenceArray, traversalTreeStructure, checkCaseCondition, renderStringInTemplate, handleBreadcrumbJump, throttle, permission, getComponentParamsValue } from '@/utils/index';
    import { isNullOrEmpty, isEmptyArr, isNullOrUnDef, isContained, isArray, isEmpty, isObject } from '@/utils/is';
    import dayjs from 'dayjs';
    import { getPagePcChartsDataSourceConvert } from '@/utils/chart';
    import { message, notification, Modal } from 'ant-design-vue'
    import { propertyFormatByNumber, propertyFormatByPercentage, propertyFormatByDate, parseSubFromDataList } from '@/utils/format';
    import colorTheme from '@/design/custom-theme.json';
    
    import UserTableRecords from '@/model/UserTableRecords';
    import { getAppBaseUrl } from '@/utils/index';
    import { sendToken } from "@/hooks/useIframeToken";
    import { useSystemStore } from "@/store/modules/system";
    const systemStore = useSystemStore();
    



      // 获取传入的流程ID和组件参数
      const props = defineProps({
            'processInstanceId': {
            type: [String,Number,Boolean],
            default: undefined,
        },
      })
      const immediateWatch = (source, callback) => {
        watch(source, callback, {deep: true,immediate: true })
      }



  /* -------------------------- 属性定义 -------------------------- */

      const setTimeOutList = [];
      const pageLoading = reactive({
        loading: false,
        tip: undefined
      });
      const authInfo = localGet('app-user-store');




      // 处理校验
      const setSubFormName =(parentInfo, name)=>{
        return [parentInfo.parents, parentInfo.cycleIndex, name];
      }


  /* ========================== 属性定义 ========================== */


  /* -------------------------- 元素数据引用 -------------------------- */


  /* ========================== 元素数据引用 ========================== */


  /* -------------------------- 页面数据 -------------------------- */


  /* ========================== 页面数据 ========================== */



  /* -------------------------- 响应 -------------------------- */

  /* ========================== 响应 ========================== */


  /* -------------------------- 函数 -------------------------- */

  /* ========================== 函数 ========================== */


  /* -------------------------- 页面参数 -------------------------- */

    const pageParameter_state = reactive({
        'processInstanceId': props.processInstanceId ?? route.query.processInstanceId,
    })

  /* ========================== 页面参数 ========================== */


  /* -------------------------- 组件事件处理方法 -------------------------- */

    // ---------------------------- 组件数据同步 ----------------------------

    // ============================ 组件数据同步 ============================


  /* ========================== 组件事件处理方法 ========================== */


  /* -------------------------- 生命周期 -------------------------- */
  // 用于参数变更后重新执行自定义指令
      const queryUpdateFlag = ref(0);
      onMounted(() => { ;

    });

    onUnmounted(() => {
      // 销毁定时器
      setTimeOutList.forEach(({ repeat, timer }) => {
        repeat ?  clearInterval(timer): clearTimeout(timer);
      });
    });

  /* ========================== 生命周期 ========================== */


  /* -------------------------- 数据关联处理 -------------------------- */





  /* -------------------------- 表单数据同步 -------------------------- */
  /* ========================== 表单数据同步 ========================== */

  /* ========================== 数据关联处理 ========================== */


  /* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */

  /* ========================== 不同组件自定义的处理逻辑 ========================== */


  // ================================定制化逻辑========================================
  onMounted(() => {
          const urlParams = new URLSearchParams(window.location.search)
          if (urlParams) {
              // 获取单个参数
              state.detailId = urlParams?.get('id')
              state.from = urlParams?.get('from')
          }
          getData()
          document.addEventListener('click', e => {
              const target = e.target as HTMLElement
              if (target.tagName === 'IMG' && target.classList.contains('previewable-image')) {
                  const imgUrl = target.getAttribute('src')
                  if (imgUrl) {
                      // 预览逻辑，如弹窗显示 imgUrl
                      previewImage(imgUrl)
                  }
              }
          })
      })
      function previewImage(url) {
          const imgWindow = window.open()
          if (imgWindow) {
              imgWindow.document.write(`<img src="${url}" style="max-width:100%"/>`)
          }
      }
      const state = reactive({
          keyWords: undefined,
          id: undefined,
          detailId: undefined,
          from: undefined,
          dataList: [],
          answerVisible: false,
          addOrEditFaqVisible: false,
          modalForm: {
              'problemName': undefined,
              'scene': undefined,
              'stageNames': undefined,
              'labels': undefined
          },
          dataLoading: false,
          addLoading: false,
          answerLoading: false,
          answerForm: {
              answer: undefined
          },
          addOrEditTitle: ''
      })
      const colorList = ['#EDF9E8', '#FEF3E7 ', 'orange']
      function debounce(fn, delay = 300) {
          let timer = null
          return function (...args) {
              if (timer) clearTimeout(timer)
              timer = setTimeout(() => {
                  fn.apply(this, args)
              }, delay)
          }
      }

      const debouncedGetData = debounce(getData, 300)
      function getData() {
          state.dataloading = true
          post(`/solution-ppm/api/v2/built-in-system-ppm/qa/question/search`, {
              keywords: state.keyWords,
              stageNames: state.detailId
              // pageNo:pagination.value.current,
              // pageSize:pagination.value.pageSize
          })
              .then(data => {
                  if (data.code !== 200) {
                      state.dataList = []
                      message.error(data.message)
                      return
                  }
                  state.dataList = data.data
                  // state.dataList = data.data.content
                  // pagination.value.total = data.data.totalElements
              })
              .finally(() => {
                  state.dataloading = false
              })
      }
      function resetData() {
          state.keyWords = undefined
          getData()
      }
      function jumpDetail(id) {
          window.open(`${import.meta.env.VITE_PUBLIC_PATH}/page/3000001017?id=${id}`, '_blank')
      }
      function handleAddFaq() {
          state.addOrEditTitle = '新建FAQ'
          state.addOrEditFaqVisible = true
      }
      function cancelAdd() {
          state.addOrEditFaqVisible = false
          state.modalForm = {
              'problemName': undefined,
              'scene': undefined,
              'stageNames': undefined,
              'labels': undefined
          }
          currentFaq.value = {}
      }
      const faqRef = ref(null)
      const answerRef = ref(null)
      const currentFaq = ref({})
      function handleConfirmFaq() {
          faqRef.value.validate().then(() => {
              state.addLoading = true
              const api = currentFaq.value.id ? put : post
              api('/solution-ppm/api/v2/built-in-system-ppm/qa/question', state.modalForm)
                  .then(data => {
                      if (data.code !== 200) {
                          message.error(data.message)
                          return
                      }
                      message.success(data.message)
                      cancelAdd()
                      getData()
                  })
                  .finally(() => {
                      state.addLoading = false
                  })
          })
      }
      function handlEditFaq(item) {
          let record = cloneDeep(item)
          currentFaq.value = record
          state.addOrEditTitle = '编辑问题'
          Object.assign(state.modalForm, record)
          state.addOrEditFaqVisible = true
      }
      function handleConfirmDelete(id) {
          del(`/solution-ppm/api/v2/built-in-system-ppm/qa/question/${id}`).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              message.success(data.message)
              getData()
          })
      }
      // function handleConfirmAnswer() {
      //     answerRef.value.validate().then(() => {
      //         state.answerLoading = true
      //         post('/solution-ppm/api/v2/built-in-system-ppm/qa/answer', {
      //             ...state.answerForm,
      //             questionId: currentFaq.value.id
      //         })
      //             .then(data => {
      //                 if (data.code !== 200) {
      //                     message.error(data.message)
      //                     return
      //                 }
      //                 message.success(data.message)
      //                 cancelAnswer()
      //                 getData()
      //             })
      //             .finally(() => {
      //                 state.answerLoading = false
      //             })
      //     })
      // }
      function handleConfirmAnswer() {
          answerRef.value.validate().then(async () => {
              state.answerLoading = true
              // 富文本
              const deltaContent = quillEditor.value.getContents()

              const imageUploadPromises = []

              deltaContent.ops.forEach(op => {
                  if (op.insert && op.insert.image && op.insert.image.startsWith('data:')) {
                      const localSrc = op.insert.image

                      // 如果是 base64 图片，上传并替换为 URL
                      const file = dataURLtoFile(localSrc, 'image.png') // 将 base64 转换为 File 对象

                      const uploadPromise = uploadFileAPI(file).then(({ data: { fullUrl } }) => {
                          // 替换 op 中的 base64 URL 为服务器返回的 URL
                          op.insert.image = fullUrl
                      })

                      imageUploadPromises.push(uploadPromise)
                  }
              })
              // 富文本
              try {
                  await Promise.all(imageUploadPromises)
                  const params = {
                      answer: JSON.stringify(deltaContent),
                      id: undefined,
                      questionId: undefined
                  }
                  const api = currentAnswer.value.id ? put : post
                  if (currentAnswer.value.id) {
                      params.id = currentAnswer.value.id
                      params.questionId = undefined
                  } else {
                      params.questionId = currentFaq.value.id
                      params.id = undefined
                  }
                  api('/solution-ppm/api/v2/built-in-system-ppm/qa/answer', params)
                      .then(data => {
                          if (data.code !== 200) {
                              message.error(data.message)
                              return
                          }
                          message.success(data.message)
                          cancelAnswer()
                          getData()
                      })
                      .finally(() => {
                          state.answerLoading = false
                      })
              } catch (error) {
                  state.answerLoading = false
                  console.error('图片上传失败', error)
                  return // 终止提交
              }
          })
      }
      function cancelAnswer() {
          state.answerVisible = false
          state.answerForm = {
              answer: undefined
          }
          currentFaq.value = {}
      }
      import { nextTick } from 'vue'
      function handleShowAnswer(item) {
          console.log(item)
          currentFaq.value = item
          state.answerVisible = true
          nextTick(() => {
              initTitle()
          })
      }
      function getBodyStyle() {
          if (state.from) {
              return {
                  padding: '24px'
              }
          } else {
              return {
                  padding: '0'
              }
          }
      }
      const pageSizeChange = (current, size) => {
          pagination.value.current = current
          pagination.value.pageSize = size
          getData()
      }
      const pageChange = (page, pageSize) => {
          pagination.value.current = page
          pagination.value.pageSize = pageSize
          getData()
      }
      const pagination = ref({
          current: 1,
          pageSize: 20,
          showSizeChanger: true,
          total: 0,
          pageSizeOptions: ['20', '40', '60', '80', '100'],
          showTotal: total =>
              `共 ${total} 个项目 第 ${pagination.value.current}/${Math.ceil(total / pagination.value.pageSize)}页`
      })
      function escapeHtml(str) {
          return str
              .replace(/&/g, '&amp;')
              .replace(/</g, '&lt;')
              .replace(/>/g, '&gt;')
              .replace(/"/g, '&quot;')
              .replace(/'/g, '&#039;')
      }

      function formatText(text, isExpanded) {
          const escaped = escapeHtml(text)
          return isExpanded ? escaped.replace(/\n/g, '<br/>') : escaped.replace(/[\n\r\t]+/g, ' ').replace(/\s+/g, ' ')
      }

      const expandedIndex = ref(null)

      function toggleExpand(index) {
          expandedIndex.value = expandedIndex.value === index ? null : index
      }
      const currentAnswer = ref({})
      //     编辑回答
      function handleEditAnswer(item, index) {
          console.log(item)
          currentAnswer.value = item
          state.answerVisible = true
          nextTick(() => {
              const editor = quillEditor.value
              const content = item.answer

              let delta

              // 尝试解析成 JSON
              if (typeof content === 'string') {
                  try {
                      const parsed = JSON.parse(content)
                      // 判断是不是合法的 Delta 格式
                      if (parsed && typeof parsed === 'object' && Array.isArray(parsed.ops)) {
                          delta = parsed
                      }
                  } catch (e) {
                      // 不是 JSON，继续走后面的纯文本逻辑
                  }
              }

              if (delta) {
                  // 是合法 Delta，直接设置
                  editor.setContents(delta)
              } else {
                  // 清空编辑器内容，插入纯文本
                  editor.setText(typeof content === 'string' ? content : String(content || ''))
              }
          })
      }
      //     删除回答
      function handleConfirmDeleteAnswer(id) {
          del(`/solution-ppm/api/v2/built-in-system-ppm/qa/answer/${id}`).then(data => {
              if (data.code !== 200) {
                  message.error(data.message)
                  return
              }
              message.success(data.message)
              getData()
          })
      }
      //     置顶非置顶
      function changeStatus(item) {
          item.loading = true
          console.log(item)
          put('/solution-ppm/api/v2/built-in-system-ppm/qa/answer/display', {
              ...item,
              display: item.display == 1 ? 0 : 1
          })
              .then(data => {
                  if (data.code !== 200) {
                      message.error(data.message)
                      return
                  }
                  message.success(data.message)
                  getData()
              })
              .finally(() => {
                  item.loading = false
              })
      }
      import { QuillEditor, Quill } from '@vueup/vue-quill'
      import ImageUploader from 'quill-image-uploader'
      import '@vueup/vue-quill/dist/vue-quill.snow.css'
      const titleConfig = [
          { Choice: ' .ql-bold', title: '加粗' },
          { Choice: ' .ql-italic', title: '斜体' },
          { Choice: ' .ql-underline', title: '下划线' },
          { Choice: ' .ql-strike', title: '删除线' },
          { Choice: ' .ql-blockquote', title: '块引用' },
          { Choice: ' .ql-code-block', title: '插入代码' },
          { Choice: ' .ql-size', title: '字体大小' },
          { Choice: ' .ql-size', title: '字体大小' },
          { Choice: ' .ql-color', title: '字体颜色' },
          { Choice: ' .ql-background', title: '字体背景颜色' },
          { Choice: ' .ql-list[value="ordered"]', title: '有序列表' },
          { Choice: ' .ql-list[value="bullet"]', title: '无序列表' },
          { Choice: ' .ql-header[value="1"]', title: '1级标题' },
          { Choice: ' .ql-header[value="2"]', title: '2级标题' },
          { Choice: ' .ql-align', title: '对齐方式' },
          { Choice: ' .ql-clean', title: '清除字体格式' },
          { Choice: ' .ql-image', title: '图像' },
          { Choice: ' .ql-size .ql-picker-item[data-value="small"]', title: '小号' },
          { Choice: ' .ql-size .ql-picker-item[data-value="large"]', title: '大号' },
          { Choice: ' .ql-size .ql-picker-item[data-value="huge"]', title: '超大号' },
          { Choice: ' .ql-size .ql-picker-item:nth-child(2)', title: '标准' },
          { Choice: ' .ql-align .ql-picker-item:first-child', title: '居左对齐' },
          { Choice: ' .ql-align .ql-picker-item[data-value="center"]', title: '居中对齐' },
          { Choice: ' .ql-align .ql-picker-item[data-value="right"]', title: '居右对齐' },
          { Choice: ' .ql-align .ql-picker-item[data-value="justify"]', title: '两端对齐' }
      ]
      // 注册图片上传模块
      Quill.register('modules/imageUploader', ImageUploader)

      // 将本地文件转换为URL
      const getLocalImageURL = file => {
          return new Promise(resolve => {
              const reader = new FileReader()
              reader.onload = e => {
                  resolve(e.target.result)
              }
              reader.readAsDataURL(file)
          })
      }

      // 表单数据

      // Quill 编辑器选项
      const editorOption = ref({
          modules: {
              // imageUploader: {
              //     upload: async file => {
              //         const localUrl = await getLocalImageURL(file)
              //         return localUrl // 返回本地图片的 URL 进行预览
              //     }
              // },
              toolbar: [
                  ['bold', 'italic', 'underline', 'strike'], // 加粗，斜体，下划线，删除线
                  ['blockquote', 'code-block'], // 引用，代码块
                  [{ header: 1 }, { header: 2 }], // 标题1，标题2
                  [{ list: 'ordered' }, { list: 'bullet' }], // 有序列表，无序列表
                  [{ size: ['small', false, 'large', 'huge'] }], // 文字大小
                  [{ color: [] }, { background: [] }], // 字体颜色，背景颜色
                  [{ align: [] }], // 对齐
                  ['clean'], // 清除格式
                  ['image'] // 链接，图片，视频
              ]
              // ImageUploader: imageHandler
          }
      })

      // 将 dataURL 转换为 File 对象的辅助函数
      const dataURLtoFile = (dataurl, filename) => {
          const arr = dataurl.split(',')
          const mime = arr[0].match(/:(.*?);/)[1]
          const bstr = atob(arr[1])
          let n = bstr.length
          const u8arr = new Uint8Array(n)
          while (n--) {
              u8arr[n] = bstr.charCodeAt(n)
          }
          return new File([u8arr], filename, { type: mime })
      }

      function initTitle() {
          document.getElementsByClassName('ql-editor')[0].dataset.placeholder = ''
          for (let item of titleConfig) {
              let tip = document.querySelector('.ql-toolbar' + item.Choice)
              if (!tip) continue
              tip.setAttribute('title', item.title)
          }
      }
      const quillEditor = ref(null)
      // 上传API
      const uploadFileAPI = async file => {
          const data = new FormData()
          data.append('file', file)

          return post('/file-storage/api/v1/file/upload', data)
              .then(({ data: { fullUrl } }) => {
                  return { data: { fullUrl } }
              })
              .catch(error => {
                  console.error('上传图片出错:', error)
                  throw error // 抛出错误以供外部处理
              })
      }
      import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html'
      function getHtmlContent(input) {
          if (!input) return ''
          let deltaObj = null
          try {
              const parsed = typeof input === 'string' ? JSON.parse(input) : input
              if (parsed?.ops && Array.isArray(parsed.ops)) {
                  deltaObj = parsed
              }
          } catch (e) {}

          if (deltaObj) {
              try {
                  const converter = new QuillDeltaToHtmlConverter(deltaObj.ops, {
                      inlineStyles: false
                  })
                  let html = converter.convert()

                  // 预览支持：用原生 <img> 包裹在一个带点击预览功能的 <a> 中
                  html = html.replace(/<img[^>]*src="([^"]+)"[^>]*>/g, (match, src) => {
                      return `<img src="${src}" class="previewable-image" title="点击查看图片"/>`
                  })

                  return html
              } catch (err) {
                  console.error('富文本转HTML失败', err)
                  return ''
              }
          }

          return String(input).replace(/\n/g, '<br/>')
      }
</script>
<style lang="less" scoped>
  .page_root {
  width: 100%;
  height: 100%;
  overflow: auto;
  }
  .page_root :deep(.@{ant-prefix}-spin-nested-loading),
  .page_root :deep(.@{ant-prefix}-spin-container)
   {
      height: 100%;
  }
  .page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper)
   {
      display: flex;
      flex-flow: column nowrap;
      justify-content: flex-start;
  }
  .page_root :deep(.@{ant-prefix}-table)
   {
    flex: auto;
    overflow: auto;
  }
  .table-moreBtn_down {
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis; width: 100px;
  }

  .table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
    background: #ebf1ff;
  }

  /*  表格树结构样式处理，展开按钮层级增加*/
  :deep(.@{ant-prefix}-table-row-expand-icon) {
    z-index: 1;
  }
  /*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
  :deep(.@{ant-prefix}-table-row-level-1 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 15px !important;
    width: calc(100% - 15px);
  }
  :deep(.@{ant-prefix}-table-row-level-2 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 30px !important;
    width: calc(100% - 30px);
  }
  :deep(.@{ant-prefix}-table-row-level-3 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 45px !important;
    width: calc(100% - 45px);
  }
  :deep(.@{ant-prefix}-table-row-level-4 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 60px !important;
    width: calc(100% - 60px);
  }

  /* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
  :deep(.@{ant-prefix}-transfer-list)
   {
      height: 100%;
      width: 50%;
  }
  .vid_wbjfcw4z9r{
      padding-top:24px;
      padding-bottom:24px;
      background-color:#FE0404
  }
  .vid_i9qutm9s24{
      box-shadow:0px 0px 0px 0px
  }
  .vid_230y7a3epu{
      box-shadow:0px 0px 0px 0px
  }
  .vid_zvzhxtmham{
      box-shadow:0px 0px 0px 0px
  }
  .vid_0qeikpreii{
      box-shadow:0px 0px 0px 0px
  }

  /*
      样式
      */
      .page_root {
          position: relative;
      }
      .body {
          height: 100vh;
          background-color: #fff;
          overflow: hidden;
          position: relative;
      }
      .title {
          display: flex;
          justify-content: space-between;
          align-items: center;
      }
      .title-font {
          margin-top: 10px;
          padding-left: 8px;
          font-size: 16px;
          height: 16px;
          line-height: 16px;
          border-left: 4px solid #3875ff;
          display: flex;
          justify-content: space-between;
          margin-bottom: 20px;
          font-weight: 600;
      }
      .gd-template-scroll {
          overflow-y: auto;
          overflow-x: hidden;
          height: calc(100% - 250px);
      }
      .gd-item {
          box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.2);
          margin: 2px;
          margin-bottom: 24px;
          padding-bottom: 16px;
      }
      .gd-item:last-child {
          margin-bottom: 5px;
      }
      .template-item-title {
          width: 100%;
          padding: 16px 24px;
          padding-bottom: 0;
          gap: 24px;
          display: flex;

          background: rgba(56, 117, 255, 0.05);
      }
      .item-top {
          display: flex;
          justify-content: space-between;
      }
      .item-top:first-child {
          border: none;
      }
      .top-left-div {
          display: flex;
          align-items: center;
      }

      .item-name {
          color: #262626;
          letter-spacing: 0;
          display: block; /* 确保其为块级元素 */
          max-width: 100%; /* 确保宽度有限制 */
          font-size: 18px;
          color: #262626;
          letter-spacing: 0;
          font-weight: 600;
          display: flex;
          gap: 8px;
          cursor: pointer;
      }
      .top-right-div {
          flex: 1;
          display: flex;
          align-items: center;
      }

      .bottom-top-item:first-child {
          padding-right: 8px;
      }
      .bottom-top-item:nth-child(n + 2) {
          padding-left: 8px;
      }
      .bottom-top-item:not(:last-child):nth-last-child(n + 2) {
          border-right: 1px solid #d9d9d9;
      }
      .item-icon {
          margin-top: 10px;
          display: flex;
          padding-left: 24px;
          flex-wrap: wrap;
          gap: 8px; /* 可选：让 tag 之间有间距 */
          margin-bottom: 10px;
      }
      :deep(.ant3-tag) {
          margin: 0;
          border-radius: 4px;
          font-size: 14px;
      }
      .item-left {
          width: 90%;
      }
      .add-or-edit-faq :deep(.ant3-form-item-label) {
          width: 80px;
      }
      .no-data-msg {
          position: absolute;
          top: 61%;
          left: 50%;
          transform: translate(-50%, -50%);
          color: #595959;
      }
      .no-data-img {
          width: 66px;
          height: 80px;
          background-image: url('@/assets/images/f4999963200e6893629a63a4a771ba2a.png');
          background-size: cover;
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
      }
      .pagination-div {
          position: absolute;
          right: 30px;
          bottom: 200px;
          padding: 10px;
          background: transparent; /* 可选：为背景添加颜色 */
      }
      .answer-item {
          margin-top: 16px;
          border-bottom: 1px solid #d9d9d9;
      }
      .answer-item:last-child {
          border: none;
      }
      .answer-content {
          font-size: 16px;
          justify-content: space-between;
          display: flex;
          padding: 0 24px;
          font-weight: 400;
          color: #262626;
      }
      .answer-content-collapsed {
          display: -webkit-box;
          -webkit-line-clamp: 2; /* 最多显示2行 */
          -webkit-box-orient: vertical;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: normal; /* 允许自动换行，但不会按 \n 分行 */
      }
      .count {
          color: #3875ff;
          //position: relative;
      }
      .count-under {
          width: 100%;
          height: 4px;
          opacity: 0.54;
          background-image: linear-gradient(180deg, #8caeff 0%, rgba(140, 174, 255, 0) 100%);
          position: relative;
          //left: 50%;
          //transform: translateX(-50%);
          bottom: 5px;
          right: -0.5px;
      }
      :deep(.ql-toolbar) {
          background: #fafafa;
          border: 1px solid #d9d9d9;
          border-radius: 2px 2px 0 0;
      }
      :deep(.ql-blank) {
          min-height: 110px;
          background: #ffffff;
      }
      :deep(.ql-editor) {
          min-height: 110px;
          background: #ffffff;
      }
      .add-or-edit-faq :deep(.ql-snow .ql-editor) img {
          width: 200px;
      }
      .answer-preview {
          display: -webkit-box;
          -webkit-box-orient: vertical;
          -webkit-line-clamp: 16;
          overflow: hidden;
          white-space: normal;
          line-height: 1.5em;
          word-break: break-word;
          max-height: 15em; /* 10 行 × 1.5em */
      }

      .answer-preview.expanded {
          -webkit-line-clamp: unset;
          max-height: none;
      }
      .icon-main {
          display: flex;
          justify-content: space-between;
          align-items: center;
          background: rgba(56, 117, 255, 0.05);
          gap: 24px;
          padding-right: 24px;
      }
      .item-bottom {
          display: flex;
          justify-content: end;
          height: 16px;
          line-height: 16px;
          flex-shrink: 0; /* 防止压缩 */
      }
      .bottom-top-msg {
          font-size: 12px;
          color: #262626;
          letter-spacing: 0;
          line-height: 17px;
          font-weight: 500;
      }
      .bottom-top-title {
          font-size: 12px;
          color: #595959;
          letter-spacing: 0;
          line-height: 17px;
          font-weight: 400;
      }
      .btn-title {
          display: flex;
          padding: 0 24px;
          margin-bottom: 8px;
          justify-content: space-between;
      }
      .btn-left {
          display: flex;
          align-items: center;
          font-size: 16px;
          color: #262626;
          letter-spacing: 0;
          font-weight: 600;
          gap: 8px;
      }
      .btn-img {
          width: 16px;
          height: 16px;
          background-size: cover;
          background-image: url('@/assets/images/f7311cccf3ca0a5091f1720d267e23d6.png');
      }
      .line {
          height: 16px;
          width: 1px;
          background: #3875ff;
      }
</style>